﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.IO;

namespace MvcOSGi.Shell.Infra
{
    public static class StringExtensions
    {
        public static bool Eqic(this string s, string value)
        {
            return string.Equals(s, value, StringComparison.OrdinalIgnoreCase);
        }

        /// <summary>
        /// Parses a string into an Enum
        /// </summary>
        /// <typeparam name="T">The type of the Enum</typeparam>
        /// <param name="value">String value to parse</param>
        /// <returns>The Enum corresponding to the stringExtensions</returns>
        public static T EnumParse<T>(this string value)
        {
            return StringExtensions.EnumParse<T>(value, false);
        }


        /// <summary>
        /// Parses a string to replace nth occurance of a pattern,
        /// </summary>
        /// <param name="value">String value to parse</param>
        /// <param name="occurence">N the occurance</param>
        /// <param name="Find">find key</param>
        /// <param name="replace">replace with</param>
        /// <returns>Nth occurance replaced string.</returns>
        public static string Replace(this string value, int occurence, string Find, string replace)
        {
            int CheckOcuuerence = 1;
            string NewString = value;
            while (NewString.IndexOf(Find) != -1)
            {
                if (occurence < CheckOcuuerence)
                {
                    string temp = value.Substring(0, value.Length - NewString.Length);
                    return temp.Replace(Find, replace) + NewString;
                }
                else
                {
                    int a = NewString.IndexOf(Find) + Find.Length;
                    NewString = NewString.Substring(a);
                    CheckOcuuerence++;
                }
            }
            return string.Empty;
        }

        public static T EnumParse<T>(this string value, bool ignorecase)
        {

            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            value = value.Trim();

            if (value.Length == 0)
            {
                throw new ArgumentException("Must specify valid information for parsing in the string.", "value");
            }

            Type t = typeof(T);

            if (!t.IsEnum)
            {
                throw new ArgumentException("Type provided must be an Enum.", "T");
            }

            return (T)Enum.Parse(t, value, ignorecase);
        }

        /// <summary>
        /// Get the parsed Integer Value - may need to extend for other types as well
        /// </summary>
        /// <param name="s">Input String</param>
        /// <param name="value">Out parameter for result</param>
        public static int GetParsedIntegerValue(this string s)
        {
            int value;
            Int32.TryParse(s, out value);
            return value;
        }

        /// <summary>
        /// Remove HTML tags from string using char array.
        /// </summary>
        public static string RemoveHTMLTags(this string source)
        {
            if (String.IsNullOrEmpty(source))
                return source;
            char[] array = new char[source.Length];
            int arrayIndex = 0;
            bool inside = false;

            for (int i = 0; i < source.Length; i++)
            {
                char let = source[i];
                if (let == '<')
                {
                    inside = true;
                    continue;
                }
                if (let == '>')
                {
                    inside = false;
                    continue;
                }
                if (!inside)
                {
                    array[arrayIndex] = let;
                    arrayIndex++;
                }
            }
            return new string(array, 0, arrayIndex);
        }

        public static string EvaluateFraction(this string sValue)
        {
            // *******************************************************************
            //  Purpose:  This function is called to convert a fraction to a decimal
            //  Created:  
            //  Modified:  rss
            // *******************************************************************
            string retValue = string.Empty;
            if (sValue == null)
            {
                return retValue;
            }
            try
            {
                sValue = sValue.Trim();
                double nNumerator = 0;
                double nDenominator = 0;
                double nWholeNumber = 0;
                int nSlashPos = 0;
                int nDashPos1 = 0;
                //for negative symbol 
                int nDashPos2 = 0;
                //for separator
                int nSpacePos = 0; //for Space - 1 1/4
                double dValue = 0;

                nSlashPos = sValue.IndexOf("/");
                nDashPos1 = sValue.IndexOf("-");
                nDashPos2 = sValue.LastIndexOf("-");
                nSpacePos = sValue.IndexOf(" ");

                if (nSpacePos > 0 && nSlashPos > 0)
                { 
                    //positive and whole number with fraction 1 1/4
                    string firstValue = sValue.Substring(0, nSpacePos).Trim();
                    string secondValue = sValue.Substring(nSpacePos).Trim();
                    nSlashPos = secondValue.IndexOf("/");
                    nNumerator = Convert.ToDouble(secondValue.Substring(0, nSlashPos));
                    nDenominator = Convert.ToDouble(secondValue.Substring(nSlashPos + 1));
                    dValue = double.Parse(firstValue) + (nNumerator / nDenominator);
                }
                else if ((nDashPos1 == -1) && (nSlashPos > 0))
                {
                    // positive and no whole number 1/4
                    nNumerator = Convert.ToDouble(sValue.Substring(0, nSlashPos));
                    nDenominator = Convert.ToDouble(sValue.Substring(nSlashPos + 1));
                    dValue = (nNumerator / nDenominator);
                }
                else if ((nDashPos1 == nDashPos2) && (nDashPos1 == 0) && (nSlashPos > 0))
                {
                    // negative and no whole number -1/4 
                    nNumerator = Convert.ToDouble(sValue.Substring(0, nSlashPos));
                    nDenominator = Convert.ToDouble(sValue.Substring(nSlashPos + 1));
                    dValue = (nNumerator / nDenominator);
                }
                else if ((nDashPos1 == nDashPos2) && (nDashPos1 > 0) && (nSlashPos > 0))
                {
                    // positive and whole number 2-1/4
                    nWholeNumber = Convert.ToDouble(sValue.Substring(0, nDashPos1));
                    nNumerator = Convert.ToDouble(sValue.Substring(nDashPos1 + 1, (nSlashPos - (nDashPos1 + 1))));
                    nDenominator = Convert.ToDouble(sValue.Substring(nSlashPos + 1));
                    dValue = (nWholeNumber + (nNumerator / nDenominator));
                }
                else if ((nDashPos2 > 0) && (nSlashPos > 0))
                {
                    // negative and whole number -2-1/4
                    nWholeNumber = Convert.ToDouble(sValue.Substring(0, nDashPos2));
                    nNumerator = Convert.ToDouble(sValue.Substring(nDashPos2 + 1, (nSlashPos - (nDashPos2 + 1))));
                    nDenominator = Convert.ToDouble(sValue.Substring(nSlashPos + 1));
                    dValue = (nWholeNumber - (nNumerator / nDenominator));
                }
                else
                    dValue = Convert.ToDouble(sValue);

                retValue = dValue.ToString();
            }
            catch (Exception excp)
            {
                throw new ArgumentException(String.Format("EvaluateFraction failed for sValue-{0}. Execption: {1}", sValue, excp.Message));
            }
            return retValue;
        }

        public static string SetUrlParameter(this string url, string paramName, string value)
        {
            return new Uri(url).SetParameter(paramName, value).ToString();
        }

        public static Uri SetParameter(this Uri url, string paramName, string value)
        {
            var queryParts = System.Web.HttpUtility.ParseQueryString(url.Query);
            queryParts[paramName] = value;
            return new Uri(url.AbsoluteUriExcludingQuery() + '?' + queryParts.ToString());
        }

        public static string AbsoluteUriExcludingQuery(this Uri url)
        {
            return url.AbsoluteUri.Split('?').FirstOrDefault() ?? String.Empty;
        }
    }
}
